/**
 * Class containing the functions to do with the WFS interface and
 * vector layer.
 *
 * @constructor
 */
function WFS() {
    "use strict";
    /**
     * Creates a filter that combines the name of the place
     * to search for and a property for that place.
     *
     * @param {object} filter An OpenLayers filter object.
     * @returns An OpenLayers filter object.
     */
    function addLocationTypeFilter(filter) {
        var filter2,
            typeCode,
            type = $("#locationType").val(),
            locationtypes = new setJSONdata("location_types");
        typeCode = locationtypes[type];
        if (typeCode !== undefined) {
            filter2 = new Filters().createFilter("pnr:paikkatyyppiKoodi", typeCode);
            filter = new Filters().createAndFilter(filter, filter2);
        }
        return filter;
    }

    /**
     * Function creates an OpenLayers filter combining the given filter which
     * distinctly searches for user inputted municipalities.
     *
     * @param {object} filter An OpenLayers filter
     * @returns An OpenLayers filter with possible municialities added.
     */
    function addMunicipalityFilter(filter) {
        var municipality,
            municipalities = setJSONdata("municipalities"),
            municipalityCode,
            filter2,
            filter3 = filter,
            i;

        if ($("#municipalityBox").val().length > 0) {
            municipality = $("#municipalityBox").val().split(",");
            for (i in municipality) {
                municipality[i] = municipality[i].toLowerCase();
                municipality[i] = municipality[i].replace(/^\s+|\s+$/g, '');
                municipality[i] = municipality[i].charAt(0).toUpperCase() +
                    municipality[i].slice(1);
                municipalityCode = municipalities[municipality[i]];
                if (municipalityCode !== undefined) {
                    if (municipalityCode.length < 3) {
                        municipalityCode = "00".concat(municipalityCode);
                        municipalityCode = municipalityCode.substring(municipalityCode.length-3,
                                                                    municipalityCode.length);
                    }

                    if (filter3 === filter) {
                        filter2 = new Filters().createFilter("pnr:kuntaKoodi", municipalityCode);
                        filter3 = new Filters().createAndFilter(filter, filter2);
                    }
                    else {
                        filter2 = new Filters().createFilter("pnr:kuntaKoodi", municipalityCode);
                        filter2 = new Filters().createAndFilter(filter, filter2);
                        filter3 = new Filters().createOrFilter(filter3, filter2);
                    }
                }
            }
        }
        return filter3;
    }

    /**
     * Adds the possible properties of all places to a drop down
     * list from which it is possible to select a specific
     * property which will be combined with the search term.
     */
    this.populateLocationTypeSelection = function () {
        var i,
            j = 1,
            select = document.getElementById("locationType"),
            locationtypes = new setJSONdata("location_types"),
            locationtypesfin = [];
        for (i in locationtypes) {
            if (locationtypes[i].fin !== undefined) {
                locationtypesfin.push(locationtypes[i].fin);
            }
        }
        locationtypesfin.sort();
        if (select) {
            select[0] = new Option("Kaikki paikat", 0);
            for (i in locationtypesfin) {
                    select[j] = new Option(locationtypesfin[i]);
                    j++;
            }
        }
    };

    /**
     * The function creates a new request to the land survey interface with
     * the filter that it updates from user input. The request is sent
     * on for searching the land survey interface.
     *
     * @param {object} map The OpenLayers map object.
     * @param {object} wfs The OpenLayers vector layer object.
     * @param {string} wfs url The url for the land survey WFS interface.
     * @param {object} filter The OpenLayers filter object to be used (or updated).
     * @param {string} feature type The type of the feature to search for.
     */
    this.updateMap = function (map, wfs, wfs_url, filter, feature_type) {
        var wfs_protocol,
            filter2;

        $(".navibutton").removeClass('activebutton');
        $("#resultslink").addClass('activebutton');
        $("#results").show();
        $("#info").hide();
        $("#searchoptions").hide();   
        $(".ui-autocomplete").hide();
        $("#sidepanel").addClass('search-indicator');

        if ($("#locationType").val() !== "Kaikki paikat") {
            filter = addLocationTypeFilter(filter);
        }

        if ($("#municipalityBox").val().length > 0) {
            filter = addMunicipalityFilter(filter);
        }

        wfs_protocol = this.createProtocol(wfs_url, filter, feature_type);
        readFeatures(map, wfs_protocol, wfs);
        wfs.refresh();
    };

    /**
     * Fills in the longitude and latitude fields on the search page on
     * map click.
     *
     * @param {string} lon The longitude of the source click.
     * @param {string} lat The latitude of the source click.
     */
    this.updatePointField = function (lon, lat) {
        $("#latBox").val(lat);
        $("#lonBox").val(lon);
    };

    /**
     * Creates the protocol for the land survey WFS interface search.
     *
     * @param {string} wfs_url The url of the land survey WFS interface.
     * @param {object} filter An OpenLayers filter object.
     * @param {string} feature_type The type of feature being searched for.
     * @return An OpenLayers WFS protocol.
     */
    this.createProtocol = function (wfs_url, filter, feature_type) {
        var wfs_protocol = new OpenLayers.Protocol.WFS({
            version: "1.1.0",
            url: wfs_url,
            featurePrefix: "",
            featureType: feature_type,
            srsName: "EPSG:3067",
            filter: filter
        });
        return wfs_protocol;
    };
    
    /**
     * Creates the OpenLayers vector layer for the features to be added to.
     *
     * @param {object} style_map An OpenLayers style map object.
     * @returns An OpenLayers wfs layer with a given stylemap.
     */
    this.createWFSLayer = function (style_map) {
        var wfs = new OpenLayers.Layer.Vector("Maanmittauslaitoksen WFS", {
            styleMap: style_map,
			rendererOptions: {zIndexing: true}
        });
        return wfs;
    };

    /**
     * Toggles the view between list and category listing.
     */
    this.changeListView = function () {
        if ($("#toggleListButton").val() == " Listanäkymä ") {
            $("#categoryView").hide();
            $("#toggleListButton").val(" Kategorianäkymä ");
            $("#listView").show();
        } else {
            $("#listView").hide();
            $("#toggleListButton").val(" Listanäkymä ");
            $("#categoryView").show();
        }
    };

    /**
     * Reads all features sent from the wfs interface and adds them to the wfs layer.
     * Creates a new stylemap for the wfs layer so feature size will depend on number
     * of features displayed.
     *
     * @param {object} wfs_protocol An OpenLayers protocol
     * @param {object} wfs_layer An OpenLayers vector layer that the features will be added to.
     */
    function readFeatures(map, wfs_protocol, wfs_layer) {
        return wfs_protocol.read({
            callback: function (response) {
                var features = response.features,
                    keptResults = [],
                    j,
                    i,
                    str,
                    text;
               /**
                * Reads through the response xml and finds out if a place has names in different
                * languages.
                * 
                * @param {string} xmldata XML page saved as a string. 
                * @return {object} names Object containing names for different languages.
                */
               function extractNames (xmldata) {
                    var format = new OpenLayers.Format.XML(),
                        doc = format.read(xmldata),
                        locations = format.getElementsByTagNameNS(doc, 'http://www.opengis.net/gml', 'featureMember'),
                        nodes,
                        nodeId,
                        kirjoitusasu,
                        kielikoodi,
                        kielivirallisuuskoodi,
                        kielienemmistokoodi,
                        name = {},
                        names = {};
                    for(i = 0; i<locations.length;++i){
                        nodes = format.getElementsByTagNameNS(locations[i], 'http://xml.nls.fi/Nimisto/Nimistorekisteri/2009/02', 'nimi');
                        nodeId = format.getElementsByTagNameNS(locations[i], 'http://xml.nls.fi/Nimisto/Nimistorekisteri/2009/02', 'paikkaID');
                        nodeId = format.getChildValue(nodeId[0]);
                        names[nodeId] = {};
                        for(j = 0; j<nodes.length;++j){
                            name = {};
                            kirjoitusasu = format.getElementsByTagNameNS(nodes[j], 'http://xml.nls.fi/Nimisto/Nimistorekisteri/2009/02', 'kirjoitusasu');
                            kielikoodi = format.getElementsByTagNameNS(nodes[j], 'http://xml.nls.fi/Nimisto/Nimistorekisteri/2009/02', 'kieliKoodi');
                            kielivirallisuuskoodi = format.getElementsByTagNameNS(nodes[j], 'http://xml.nls.fi/Nimisto/Nimistorekisteri/2009/02', 'kieliVirallisuusKoodi');
                            kielienemmistokoodi = format.getElementsByTagNameNS(nodes[j], 'http://xml.nls.fi/Nimisto/Nimistorekisteri/2009/02', 'kieliEnemmistoKoodi');
                            name["kirjoitusasu"] = format.getChildValue(kirjoitusasu[0]);
                            name["kieliKoodi"] = format.getChildValue(kielikoodi[0]);
                            name["kieliVirallisuusKoodi"] = format.getChildValue(kielivirallisuuskoodi[0]);
                            name["kieliEnemmistoKoodi"] = format.getChildValue(kielienemmistokoodi[0]);
                            names[nodeId][name["kieliKoodi"]] = name;
                        }
                    }
                    return names;
                }
                if (features.length > 0) {
                    var extnames = extractNames(response.priv.responseText),
                        keepResults = [];
                    //Set names in all languages for the locations;
                    for(i = 0; i < features.length; i++){
                        features[i]["names"] = {};
                        features[i]["names"] = extnames[features[i].data.paikkaID];
                    }
                    // Check whether to keep old features
                    if ($("#keepResults").is(":checked") === false) {
                        wfs_layer.destroyFeatures();
                    }
                    wfs_layer.styleMap = new Style().createStyleMap((wfs_layer.features.length + features.length), map);
                    wfs_layer.addFeatures(features);
                    new FeatureInformation(map, wfs_layer).parseFeatures(features);
                } else {
                    if ($("#keepResults").is(":checked") == false) {
                        wfs_layer.destroyFeatures();
                    }
                    if ($("#keepResults").is(":checked") == true) {
                        str = $("#resultsHeader").text();
                        text = "<div id='resultsHeader'><h2>" + str + ", \"" + $("#searchBox").val() +
                            "\", ei hakutuloksia</h2></div>";
                        $("#resultsHeader").empty().append(text);
                    } else {
                        $("#categoryView").empty().append("<div id='resultsHeader'><h2>\"" + $("#searchBox").val() +
                            "\", ei hakutuloksia.</h2></div>");
	                    $("#listView").empty().append("<div id='resultsHeader'><h2>\"" + $("#searchBox").val() + "\", ei hakutuloksia.</h2></div>");
                    }
                }           
				$("#sidepanel").removeClass('search-indicator');
            }
        });
    }
}